package per.destiny.seckill.service;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import per.destiny.seckill.mapper.OrderMapper;
import per.destiny.seckill.mapper.SeckillGoodsMapper;
import per.destiny.seckill.mapper.SeckillOrderMapper;
import per.destiny.seckill.pojo.*;
import per.destiny.seckill.vo.GoodsVo;

import java.util.Date;
import java.util.List;

@Service
public class OrderService {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private SeckillOrderMapper seckillOrderMapper;

    /**
     * 已验证，不需要额外配置，@Transactional注解已生效
     *
     * @param user
     * @param goods
     * @return
     */
    @Transactional
    public Order seckill(User user, GoodsVo goods) {
        // 获取秒杀商品
        SeckillGoods seckillGoods = this.getSeckillGoods(goods.getId());
        // 生成订单（推荐顺序，先生成订单，然后减库存。因为减库存虽然是行锁，但是其他所有请求都会要更改这条记录，在一个事务提交之前其他事务会排队，降低吞吐量）
        Order order = createOrder(user, goods);
        // 秒杀商品表减库存（推荐顺序，先生成订单，然后减库存。因为减库存虽然是行锁，但是其他所有请求都会要更改这条记录，在一个事务提交之前其他事务会排队，降低吞吐量）
        seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);
        seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
        return order;
    }

    private Order createOrder(User user, GoodsVo goods) {
        // 生成订单
        Order order = new Order();
        order.setUserId(user.getId());
        order.setGoodsId(goods.getId());
        order.setGoodsName(goods.getGoodsName());
        order.setGoodsCount(1);
        order.setGoodsPrice(goods.getSeckillPrice());
        order.setStatus(0);
        order.setCreateDate(new Date());
        order.setUpdateDate(new Date());
        orderMapper.insert(order);
        // 生成秒杀订单
        SeckillOrder seckillOrder = new SeckillOrder();
        seckillOrder.setUserId(user.getId());
        seckillOrder.setOrderId(order.getId());
        seckillOrder.setGoodsId(goods.getId());
        seckillOrderMapper.insert(seckillOrder);
        return order;
    }

    private SeckillGoods getSeckillGoods(Long goodsId) {
        SeckillGoodsExample seckillGoodsExample = new SeckillGoodsExample();
        seckillGoodsExample.createCriteria().andGoodsIdEqualTo(goodsId);
        List<SeckillGoods> seckillGoods = seckillGoodsMapper.selectByExample(seckillGoodsExample);
        if (CollectionUtils.isEmpty(seckillGoods)) {
            return null;
        }
        return seckillGoods.get(0);
    }
}
